package com.randi.monitor.service.impl;

import com.randi.common.constant.CacheConstants;
import com.randi.common.enums.ResultCode;
import com.randi.common.exception.ServiceException;
import com.randi.common.utils.RedisUtil;
import com.randi.common.utils.SecurityUtils;
import com.randi.common.utils.StringUtils;
import com.randi.common.core.domain.model.LoginUser;
import com.randi.monitor.dto.SysUserOnline;
import com.randi.monitor.service.ISysUserOnlineService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author ziye
 */
@Service
public class SysUserOnlineServiceImpl implements ISysUserOnlineService {

    @Resource
    private RedisUtil redisUtil;

    /**
     * 构建在线用户信息
     *
     * @param loginUser 登录用户信息
     * @return 在线用户信息
     */
    private SysUserOnline buildUserOnlineByLoginUser(LoginUser loginUser) {
        SysUserOnline sysUserOnline = new SysUserOnline();

        sysUserOnline.setTokenId(loginUser.getUuid());
        sysUserOnline.setUserName(loginUser.getUsername());
        sysUserOnline.setIpAddress(loginUser.getIpAddress());
        sysUserOnline.setLoginLocation(loginUser.getLoginLocation());
        sysUserOnline.setBrowser(loginUser.getBrowser());
        sysUserOnline.setOs(loginUser.getOs());
        sysUserOnline.setLoginTime(new Date(loginUser.getLoginTime()));

        return sysUserOnline;
    }

    /**
     * 过滤
     *
     * @param loginUser     登录用户
     * @param sysUserOnline 过滤条件对象
     * @return 在线用户信息
     */
    private SysUserOnline handleLoginUserEquals(LoginUser loginUser, SysUserOnline sysUserOnline) {

        if (StringUtils.isEmpty(sysUserOnline.getIpAddress()) && StringUtils.isEmpty(sysUserOnline.getUserName())) {
            return buildUserOnlineByLoginUser(loginUser);
        }

        if (StringUtils.isNotEmpty(sysUserOnline.getIpAddress()) && StringUtils.isNotEmpty(sysUserOnline.getUserName())) {
            if (StringUtils.equals(loginUser.getIpAddress(), sysUserOnline.getIpAddress()) && StringUtils.equals(loginUser.getUsername(), sysUserOnline.getUserName())) {
                return buildUserOnlineByLoginUser(loginUser);
            } else {
                return null;
            }
        }

        if (StringUtils.isNotEmpty(sysUserOnline.getIpAddress()) && StringUtils.equals(loginUser.getIpAddress(), sysUserOnline.getIpAddress())) {
            return buildUserOnlineByLoginUser(loginUser);
        }

        if (StringUtils.isNotEmpty(sysUserOnline.getUserName()) && StringUtils.equals(loginUser.getUsername(), sysUserOnline.getUserName())) {
            return buildUserOnlineByLoginUser(loginUser);
        }

        return null;
    }

    /**
     * 排序
     *
     * @param list       list
     * @param comparator 条件
     * @return sortedList
     */
    private List<SysUserOnline> handleListSorted(List<SysUserOnline> list, Comparator<SysUserOnline> comparator) {
        return list.stream().sorted(comparator).collect(Collectors.toList());
    }

    /**
     * 获取列表
     *
     * @param sysUserOnline sysUserOnline
     * @return SysUserOnline
     */
    @Override
    public List<SysUserOnline> selectOnlineUserList(SysUserOnline sysUserOnline) {
        List<SysUserOnline> userOnlineList = new ArrayList<>();

        Collection<String> keys = redisUtil.getCacheKeys(CacheConstants.LOGIN_TOKEN_ACCESS_KEY + "*");
        for (String key : keys) {
            LoginUser loginUser = redisUtil.getCache(key);
            SysUserOnline userOnline = this.handleLoginUserEquals(loginUser, sysUserOnline);
            if (userOnline != null) {
                String uuid = SecurityUtils.getLoginUser().getUuid();
                userOnline.setAllowDisable(userOnline.getTokenId().equals(uuid));
                userOnlineList.add(userOnline);
            }
        }
        Collections.reverse(userOnlineList);
        userOnlineList.removeAll(Collections.singleton(null));

        return this.handleListSorted(userOnlineList,
                Comparator.comparing(SysUserOnline::getLoginTime).reversed()
                        .thenComparing(SysUserOnline::getUserName));
    }

    /**
     * 强制退出
     *
     * @param tokenId tokenId
     */
    @Override
    public void onlineUserForceLogout(String tokenId) {
        String uuid = SecurityUtils.getLoginUser().getUuid();
        if (uuid.equals(tokenId)) {
            throw new ServiceException(ResultCode.BUSINESS_ERROR_DETAIL, "不能强制退出自己");
        }
        redisUtil.delete(CacheConstants.LOGIN_TOKEN_ACCESS_KEY + tokenId);
        redisUtil.delete(CacheConstants.LOGIN_TOKEN_REFRESH_KEY + tokenId);
    }
}
